// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 MOTOIN9_DLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何其他项目上不应定义此符号。这样，源文件中包含此文件的任何其他项目都会将
// MOTOIN9_DLL_API 函数视为是从 DLL 导入的，而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifndef MOTION9_DLL_H_
#define MOTION9_DLL_H_

#ifdef __cplusplus
extern "C" {
#endif
/*-------------------------------------------------------------------------
@brief   平台定义
--------------------------------------------------------------------------*/
#ifdef CPP_BULDER
#define CALL __stdcall
#else
#define CALL
#endif

//-----Windows platform---------
#ifdef WIN32
#define WINDOWS_P
#include <stdio.h>
#include <windows.h>
#define MOTOIN9_DLL_API __declspec(dllexport)
#define sleep_ms(x) Sleep(x)
#endif

//-----linux---------
#ifdef linux
#include <stdio.h>
#define LINUX_P
#define sleep_ms(x) usleep(x * 1000)
#define MOTOIN9_DLL_API
#endif

/*-------------------------------------------------------------------------
@brief   基本宏定义
--------------------------------------------------------------------------*/
#define MAX_JOINT 9 //定义最大关节9轴,请勿修改
//数据类型定义
#if 0
#define tchar char
#define tuchar unsigned char
#define tfloat float
#define tdouble double
#define tint int
#define tuint unsigned int
#endif

/*-------------------------------------------------------------------------
@brief   enum
--------------------------------------------------------------------------*/
//机械结构体
typedef enum {
    GANTRY = 0,  //龙门 = 3 + rx + ry + rz + uvw
    SCARA = 1,   //scara = 4 + rx + ry + uvw
    IRB_140 = 2, //abb结构 6轴末端3轴相交 irb140 = 6 + uvw
    UR_10 = 3,   //ur结构 6轴中间3轴平行 = 6 + uvw
} ENUM_MACHINE_STRUCT;

typedef enum {
    //消息回调1000-1999
    MOTION_MSG_UNDEFINE = 1000,  //无 msg=string
    MOTION_MSG_INIT_DONE = 1001, //初始化已经完成 msg=string
    MOTION_MSG_FINISH_SEGMENT = 1002, //运动控制库完成一段TP曲线

    //警告回调2000-2999
    MOTION_WARN_UNDEFINE = 2000,
    MOTION_WARN_FREE_MOVE_ERROR_INDEX = 2001, //FREE模式运动关节号错误 msg=string
    MOTION_WARN_ERROR_USER_VEL = 2002,        //速度参数错误 msg=string
    MOTION_WARN_ERROR_USER_OVL = 2003,        //逼近参数错误
    /*
	//2017-3-16-zqs:修改为只有一个速度参数错误,通过字符输出具体的速度参数
	MOTION_WARN_ERROR_USERVEL_ACCA = 2002,			//加速度参数错误
	MOTION_WARN_ERROR_USERVEL_ACCD = 2003,			//减加速度参数错误
	MOTION_WARN_ERROR_USERVEL_VEL = 2004,			//目标速度参数错误
	*/
    MOTION_WARN_WRITE_COMMAND_OR_MOVE_FOR_UN_INIT = 2005,     //motion初始化未完成,拒绝相关命令或运动 msg=string
    MOTION_WARN_WRITE_COMMAND_OR_MOVE_FOR_EMERGENCY = 2006,   //motion处于急停状态,拒绝相关命令或运动 msg=string
    MOTION_WARN_WRITE_COMMAND_OR_MOVE_FOR_PAUSE = 2007,       //motion处于暂停状态,拒绝相关命令或运动 msg=string
    MOTION_WARN_WRITE_COMMAND_OR_MOVE_FOR_ABORTINT = 2008,    //motion正在停止,拒绝相关命令或运动 msg=string
    MOTION_WARN_WRITE_PALNE_MOVE_FOR_ERROR_INTER_MODE = 2009, //未处于plane模式,无法执行plane模式下的相关运动 msg=string
    MOTION_WARN_WRITE_FREE_MOVE_FOR_ERROR_INTER_MODE = 2010,  //未处于free模式，无法执行free模型的相关运动 msg=string
    MOTION_WARN_WRITE_CMD_PALNE_FOR_FREE_RUN = 2011,          //正在执行FREE模式(且处于运动中),无法切换到PLANE模式 msg=string
    MOTION_WARN_WRITE_CMD_FREE_FOR_PLANE_RUN = 2012,          //正在执行PLANE模式(且处于运动中),无法切换到FREE模式 msg=string
    MOTION_WARN_CHANGE_VELOCITY_VEL = 2013,                   //改变速度,速度参数错误 msg=string
    MOTION_WARN_JOINT_UN_ENABLE = 2014,                       //添加了关节运动,但是相关关节未使能 msg=string
    MOTION_WARN_ADD_FREE_MOVE_FOR_JOINT_BUSY = 2015,          //添加自由运动,但相关关节忙碌 msg=string
    MOTION_WARN_CAN_NOT_RUN_CARTESIAN_NEAR_SINGULAR = 2016,   //在奇异点附近无法执行插补运动 msg=string
    MOTION_WARN_WRITE_MOVE_FOR_ERROR_OCCUR = 2017,            //发生错误,运动过程中参数错误等,无法添加运动 msg=string
    MOTION_WARN_POSE_ERROR = 2018,                            //位置逆解或者正解失败 msg=string
    MOTION_WARN_FK_FLAG_UNEQUAL_IK_FLAG = 2019,               //fk_flag != ik_flag无法启动曲线插补 msg=string
    MOTION_WARN_POSIT_OVER_SOFT_LIMIT = 2020,                 //位置超过软件限制
    MOTION_WARN_SET_POSIT_WHILE_MOVING = 2021,                //无法再运动过程中设置位置

    //错误回调3000-3999
    MOTION_ERROR_UNDEFINE = 3000,       //msg=string
    MOTION_ERROR_FOLLOW_ERROR = 3001,   //跟随误差过大 msg=string
    MOTION_ERROR_POSIT_OVER_ABS = 3002, //超过绝对位置限制
} ENUM_MOTION_CALLBACK_REASON;

//消息回调
typedef int(CALLBACK_MSG)(int reason, char *msg);
typedef int(CALLBACK_OUT)(double posti[MAX_JOINT], float vel[MAX_JOINT], float acc[MAX_JOINT]);

/*-------------------------------------------------------------------------
@brief   结构体
--------------------------------------------------------------------------*/

//机械DH参数 standard
typedef struct {
    double d;
    double th;
    double a;
    double ap;
} STRUCT_DH;

//夹具参数 standard
typedef struct {
    double x;
    double y;
    double z;
    double rx;
    double ry;
    double rz;
} STRUCT_TOOL_DESCRIPTION;

//机械臂位姿结构体
typedef struct {
    double x, y, z;    //位置
    double rx, ry, rz; //姿态rotx,roty,rotz
    double u, v, w;    //辅助轴姿态u,v,w
} STRUCT_POSE;

//坐标轴线性速度配置
typedef struct {
    float vel_start; //启动速度 mm/s
    float vel_stop;  //停止速度 mm/s
    float vel_max;   //最大速度 mm/s
    float acc_max;   //最大加速度 mm/(s*s)
} STRUCT_AXIS_LINEAR_VEL_CONF;

//坐标轴旋转度配置
typedef struct {
    float vel_start; //启动速度 rad/s
    float vel_stop;  //停止速度 rad/s
    float vel_max;   //最大速度 rad/s
    float acc_max;   //最大加速度 rad/(s*s)
} STRUCT_AXIS_ROT_VEL_CONF;

//关节速度配置
typedef struct {
    float vel_start[MAX_JOINT]; //关节空间运动启动速度 rad/s
    float vel_stop[MAX_JOINT];  //关节空间运动停止速度 rad/s
    float vel_max[MAX_JOINT];   //关节空间运动最大速度 rad/s
    float acc_max[MAX_JOINT];   //关节空间运动最大加速度 rad/s^2
} STRUCT_JOINT_VEL_CONF;

//关节空间位置限制
typedef struct {
    double limit_h[MAX_JOINT]; //关节空间位置限制最大值
    double limit_l[MAX_JOINT]; //关节空间位置限制最小值
} STRUCT_JOINT_SPACE_LIMIT;

//关节空间位置限制
typedef struct {
    double joint_max_vel[MAX_JOINT]; //关节最大速度 rad/s
    double line_max_vel;             //曲线最大速度 mm/s
    double rot_max_vel;              //姿态旋转最大速度限制
} STRUCT_VELOCITY_LIMIT;

typedef struct {
    float vel;          //目标速度
    float acca;         //加速段最大加速度
    float accd;         //减速段最大加速度
    float jerk;         //加加速度
} STRUCT_USER_VEL_BASE; //基础速度结构体

//用户速度结构
typedef struct {
    STRUCT_USER_VEL_BASE jv; //关节转动速度
    STRUCT_USER_VEL_BASE lv; //线性运动速度
    STRUCT_USER_VEL_BASE rv; //姿态旋转速度
} STRUCT_USER_VEL;

//用户运动逼近参数
typedef struct {
    float rel; //相对逼近参数(取值范围 0-1),用于点到点逼近
    float abs; //绝对位置逼近参数(取值范围 0-1000mm),用于曲线逼近---暂时无效
    float rad; //绝对姿态逼近参数(取值范围 0-1rad),用于姿态旋转逼近---暂时无效
} STRUCT_USER_OVL;

/*
控制器状态包括:
EMERGENCY: 急停（禁止除了基本设置、解除急停以外所有命令）具体见说明文档
MOVING（PLANE、FREE）: PALNE(轨迹规划),FREE(自由运动)
ABORTING: 停止中
PAUSE(DOING ): 暂停状态（暂停中和暂停完成）
*/
typedef enum {
    CMD_STATUS_MOVING_IDLE = -1, //IDLE模式
    CMD_STATUS_MOVING_FREE = 0,  //FREE模式
    CMD_STATUS_MOVING_PLANE = 1, //PLANE模式
    CMD_STATUS_EMERGENCY = 2,    //EMERGENCY模式
    CMD_STATUS_ABORTING = 3,     //执行停止
    CMD_STATUS_PAUSING = 5,      //执行暂停
    CMD_STATUS_PAUSED = 6,       //暂停完成
} ENUM_CMD_STATUS;               //控制器主状态机

typedef enum {
    JOINT_INDEX_ALL = -1,   //表示所有关节
    JOINT_INDEX_JOINT1 = 0, //表示关节1
    JOINT_INDEX_JOINT2 = 1,
    JOINT_INDEX_JOINT3 = 2,
    JOINT_INDEX_JOINT4 = 3,
    JOINT_INDEX_JOINT5 = 4,
    JOINT_INDEX_JOINT6 = 5,
    JOINT_INDEX_JOINT7 = 6,
    JOINT_INDEX_JOINT8 = 7,
    JOINT_INDEX_JOINT9 = 8,
} ENUM_JOINT_INDEX; //关节index表示

//配置结构体
typedef struct {
    //机械结构
    int machine_struct;              //机械结构
    STRUCT_DH dh_machine[6];         //最多6轴的dh参数
    STRUCT_TOOL_DESCRIPTION dh_tool; //夹具结构参数
    char joint_enable[MAX_JOINT];    //根据结构调整

    //速度配置
    char vel_type;
    STRUCT_JOINT_VEL_CONF vel_joint;      //关节空间,关节速度配置
    STRUCT_AXIS_LINEAR_VEL_CONF vel_line; //笛卡尔空间,曲线速度配置
    STRUCT_AXIS_ROT_VEL_CONF vel_rot;     //笛卡尔空间,旋转速度配置

    //运动限制
    STRUCT_JOINT_SPACE_LIMIT limit_abs;  //绝对位置限制
    STRUCT_JOINT_SPACE_LIMIT limit_soft; //软件位置限制
    STRUCT_VELOCITY_LIMIT limit_vel;     //速度限制(暂时无效)

    //其他配置
    float inter_period;       //插补周期(单位s,取值0.02s)
    float inter_period_recip; //(无需赋值)
    float inter_period_cubic; //(无需赋值)
    int look_ahead_depth;     //大于等于3
    float joint_period;       //关节伺服周期(单位s,取值0.002s）
    //callback
    CALLBACK_MSG *callback_msg;
    CALLBACK_OUT *callback_out;

    //test
    FILE *fd1;
} STRUCT_MOTION_PARM;

//=====================API========================================
/*-------------------------------------------------------------------------
@brief    初始化,配置相关
@param    InitPram   initial paramters
@return   int 0:no error -1:error
this function is used for setting the motion controller initial parameters
--------------------------------------------------------------------------*/
/*
运动控制库初始化
init_param:配置参数
-------------------
return 
0:成功
*/
MOTOIN9_DLL_API CALL int Motion_Init(STRUCT_MOTION_PARM init_param);

/*
运动控制service,周期1ms
-------------------
return： 无
*/
MOTOIN9_DLL_API CALL void Motion_Service();

/*
设置当前位置
注意：机械臂找到机械位置、或者拖拽结束之后,必须告知更新控制器当前位置
-------------------
return 
0：成功
-1：失败,motion运动过程中无法修改当前位置
*/
MOTOIN9_DLL_API CALL int Motion_SetCurrentPosition(double curr_posit[MAX_JOINT]);

MOTOIN9_DLL_API CALL void Motion_Out();
MOTOIN9_DLL_API CALL int Motion_SetTool(const STRUCT_POSE *tool);

/*-------------------------------------------------------------------------
@brief		设置控制命令
@param		null
@return
所有控制命令 return-> 0:添加成功  -1:执行失败
--------------------------------------------------------------------------*/
/*
进入PLANE模式
-------------------
return
0:成功  -1:失败
注意：
同时如果在PLANE模式发生错误,则无法继续写入plane运动命令
调用该函数会自动清除错误标志,并允许写入plane命令
*/
MOTOIN9_DLL_API CALL int Motion_CommandPlane();

/*
进入FREE模式
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandFree();

/*
急停
任何模式均会进入急停状态,且会复位处配置参数外的所有数据
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandEmergency();

/*
解除急停
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandEmergencyRelease();

/*
命令ABORT
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandAbort();

/*
命令PAUSE
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandPause();

/*
命令RESUME
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandResume();

/*
改变全局速度(进给率)
feed_rate:范围0.01-1.0
-------------------
return
0:成功 -1:失败
*/
MOTOIN9_DLL_API CALL int Motion_CommandChangeGlobleVelocity(float feed_rate);

/*-------------------------------------------------------------------------
@brief		查询命令运动完成
@param		void
@return		-1: 查询失败 0：运动完成  1->busy
--------------------------------------------------------------------------*/
MOTOIN9_DLL_API CALL int Motion_QueryMoveDone();

/*-------------------------------------------------------------------------
@brief		查询命令运动完成
@param		joint: 关节index
@return		-1: 查询失败(关节错误) 0：运动完成  1->busy
--------------------------------------------------------------------------*/
MOTOIN9_DLL_API CALL int Motion_QueryJointMoveDone(int joint);

MOTOIN9_DLL_API CALL int Motion_QueryPathBuffUsedSize();                       //查询运动缓存使用大小	return 使用大小
MOTOIN9_DLL_API CALL int Motion_QueryVersion(char *str);                       //查询控制库版本号 str:版本,版本号小于32个字节
MOTOIN9_DLL_API CALL int Motion_QueryInitial();                                //查询初始化状态	return-> 1:done 0:undone
MOTOIN9_DLL_API CALL int Motion_QueryCmdState(ENUM_CMD_STATUS *state);         //查询指令状态 参考ENUM_EX_CMD_STATE
MOTOIN9_DLL_API CALL int Motion_QueryInterplationParten();                     //查询插补工作模式 0: Idle  1:PLANE模式  2:FREE模式
MOTOIN9_DLL_API CALL int Motion_QueryConfiguration(STRUCT_MOTION_PARM *conf);  //查询当前配置
MOTOIN9_DLL_API CALL int Motion_QueryGlobleVelocity(float *vel);               //查询当前全局速度 (进给率 取值范围0.01-1.0)
MOTOIN9_DLL_API CALL int Motion_QueryExcuteId();                               //查询当前执行ID  Idle模式时Id = 0
MOTOIN9_DLL_API CALL int Motion_QueryCurrentPosition(double theta[MAX_JOINT]); //查询当前position值

/*-------------------------------------------------------------------------
@brief		查询当前位姿
@param		STRUCT_POSE *pose,当前位姿,（不可为NULL）
			int *fk_flag,当前手臂姿态,(可以为NULL)
@return		-1: 超过abs_limit查询失败, 0：查询成功
--------------------------------------------------------------------------*/
MOTOIN9_DLL_API CALL int Motion_QueryCurrentPose(STRUCT_POSE *pose, int *fk_flag); //查询当前位姿值

/*-------------------------------------------------------------------------
@brief		其他
@param		null
@return		-1: 查询失败
--------------------------------------------------------------------------*/
/*
等待运动完成
joint: -1表示等待所有关节,其他值表示相应的关节index
cycle：查询周期单位ms,内部限制了cycle必须大于5ms
time:查询次数(-1表示一直等待直到完成)
actual_done： 由于存在输出缓存FIFO,actual_done=1表示规划和运动均已结束,
	actual_done=0表示规划已经结束,所有数据已经进入缓存FIFO,但是fifo是否输出完成(don't care)
-------------------
return 
0:等待运动完成,成功
-1:等待运动完成,超时
*/
MOTOIN9_DLL_API CALL int Motion_WaitMoveDone(int cycle, int times);

/*
手掌运动学正解
posit: 关节位置 pose:笛卡尔位姿
fk_flag: 表示正向运动的姿态标志,不同机械臂fk_flag的含义不同
		-1:表示机械臂处于奇异点位置
		-2:正解失败
对于scara->0:右臂 1:左臂
对于6轴->0:表示
-------------------
return
0:均返正解完成
-1:超过绝对位置限制(limit_abs),正解失败
*/
MOTOIN9_DLL_API CALL int Motion_KmHandForward(double posit[MAX_JOINT], STRUCT_POSE *pose, int *fk_flag);

/*
夹具运动学正解
posit: 关节位置 pose:笛卡尔位姿
fk_flag: 同fk_flag
-------------------
return
0:均返正解完成
-1:超过绝对位置限制(limit_abs),正解失败
*/
MOTOIN9_DLL_API CALL int Motion_KmClampForward(double posit[MAX_JOINT], STRUCT_POSE *pose, int *fk_flag);

/*
手掌运动学逆解
posit: 关节位置 pose:笛卡尔位姿
ik_flag: 表示逆向运动学姿态
对于scara->0:右臂 1:左臂
对于6轴->0：右上翻 1：右上非
-------------------
return
0:逆解完成
-1:超过绝对位置限制(limit_abs),逆解失败
*/
MOTOIN9_DLL_API CALL int Motion_KmHandInverse(double posit[MAX_JOINT], STRUCT_POSE *pose, int ik_flag);

/*
夹具运动学逆解
posit: 关节位置 pose:笛卡尔位姿
ik_flag:同ik_flag
-------------------
return
0:逆解完成
-1:超过绝对位置限制(limit_abs),逆解失败
*/
MOTOIN9_DLL_API CALL int Motion_KmClampInverse(double posit[MAX_JOINT], STRUCT_POSE *pose, int ik_flag);

/*-------------------------------------------------------------------------
@brief		添加运动相关
@param		
UserVel:用户速度参数
UserOvl：用户Ovl参数
@return		添加运动相关 return-> 0:成功  -1:失败
--------------------------------------------------------------------------*/
//----------------------------FREE模式-----------------------------------
//自由模式关节增量运动联动
//MOTOIN9_DLL_API CALL int Motion_Add_Joint_Free_Jog_Increment_Linked(char blocking, double increment[MAX_JOINT], STRUCT_USER_VEL user_vel, int id, char enable);
//自由模式关节增量运动联动
//MOTOIN9_DLL_API CALL int Motion_Add_Joint_Free_Jog_Increment_Independence(char blocking, int joint, double increment, STRUCT_USER_VEL user_vel, int id, char enable);
//自由模式关节绝对位置运动联动
MOTOIN9_DLL_API CALL int Motion_Add_Joint_Free_Jog_Abstract_Linked(char blocking, double posit[MAX_JOINT], STRUCT_USER_VEL user_vel, int id, char enable);
//自由模式关节绝对位置独立运动
MOTOIN9_DLL_API CALL int Motion_Add_Joint_Free_Jog_Abstract_Independence(char blocking, int joint, double posit, STRUCT_USER_VEL user_vel, int id, char enable);
//自由模式坐标系运动
MOTOIN9_DLL_API CALL int Motion_Add_Axis_Free_Jog_Abstract(char blocking, STRUCT_POSE pose, int ik_flag, STRUCT_USER_VEL user_vel, int id, char enable);

//----------------------------PLANE模式-----------------------------------
//PLANE模式点到点运动-参数posit
MOTOIN9_DLL_API CALL int Motion_AddPlaneP2P_Posit(double posit[MAX_JOINT], STRUCT_USER_VEL user_vel, STRUCT_USER_OVL user_ovl, int id, char enable);
//PLANE模式点到点运动-参数pose
MOTOIN9_DLL_API CALL int Motion_AddPlaneP2P_Pose(STRUCT_POSE pose, int ik_flag, STRUCT_USER_VEL user_vel, STRUCT_USER_OVL user_ovl, int id, char enable);
//PLANE模式直线插补运动-参数pose
MOTOIN9_DLL_API CALL int Motion_AddPlaneLine_Pose(STRUCT_POSE pose, int ik_flag, STRUCT_USER_VEL user_vel, STRUCT_USER_OVL user_ovl, int id, char enable);

#ifdef __cplusplus
}
#endif

#endif
